package com.siecomzg.transport.usb;

import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.SystemClock;

import com.siecomzg.constconfig.ConstDefine;
import com.siecomzg.proto.Message;
import com.siecomzg.tool.LogUtil;
import com.siecomzg.transport.CommonClient;
import com.siecomzg.transport.SiecomDevice;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class USBClient extends CommonClient {

    private final static String TAG = USBClient.class.getSimpleName();
    private UsbDeviceConnection mUsbDeviceConnection;
    private UsbEndpoint mUsbEndpointOut;
    private UsbEndpoint mUsbEndpointIn;
    private UsbInterface mUsbInterface;
    private ExecutorService mThreadPool = null;
    private boolean mToggle = true;
    private boolean isDetached        = false;
    private static final String USB_ACTION = "com.siecom.zhq.client";
    public UsbManager mUsbManager ;
    private UsbDevice mUsbDevice;
    private static Context mContext;
    private OnUSBReceiveListen mUsbRecListen;

    public boolean isReceiverMessage = true;

    private  static USBClient mUsbClinetInstance = new USBClient();

    public static USBClient getInstance(Context context){
        if(null != context ){
            mContext = context;
        }
        return mUsbClinetInstance;
    }
    public USBClient(){

    }


    public interface OnUSBReceiveListen {

        public void onUsbMsgReceive(Message.siecomproto msg);

        public void onError(Throwable e);
    }
    public void setOnUSBReceiveListen(OnUSBReceiveListen listen){
        this.mUsbRecListen = listen;
    }
    /**
     * 打开设备 , 让平板和背夹端连起来
     */
    public int openDevices() {
        int ret = 0;
        mUsbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
        if(mThreadPool == null){
            mThreadPool = Executors.newFixedThreadPool(3);
        }
        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(USB_ACTION), 0);

        //列举设备(手机)
        HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
//        Toast.makeText(mContext,"deviceList="+deviceList.size(),Toast.LENGTH_SHORT).show();
        LogUtil.e(TAG, "USB deviceList.size == " + deviceList.size());
        if (deviceList.size() != 0) {
            for (UsbDevice usbDevice : deviceList.values()) {
                mUsbDevice = usbDevice;
                LogUtil.e(TAG, "USB 设备：pid == " + usbDevice.getProductId());
                int productId = usbDevice.getProductId();
//                Toast.makeText(mContext,"productId="+productId,Toast.LENGTH_SHORT).show();
                if (productId != 377 && productId != 7205) {
                    if (mUsbManager.hasPermission(usbDevice)) {
                        LogUtil.e(TAG, "USB 设备 拥有权限" );
                        initAccessory(usbDevice);
                    } else {
                        LogUtil.e(TAG, "USB 设备 申请权限" );
                        mUsbManager.requestPermission(usbDevice, pendingIntent);
                        LogUtil.e(TAG, "USB 设备 申请权限 完成" );
                    }
                }
            }
        } else {
//            mError.setText("请连接USB");
            LogUtil.e(TAG,"请连接USB");
            ret = -1;
        }
        return ret;
    }

    /**
     * 发送命令 , 让手机进入Accessory模式
     *
     * @param usbDevice
     */
    public void initAccessory(UsbDevice usbDevice) {
        UsbDeviceConnection usbDeviceConnection = mUsbManager.openDevice(usbDevice);
        if (usbDeviceConnection == null) {
//            mError.setText("请连接USB");
            LogUtil.e(TAG,"usbDeviceConnection 请连接USB");
            return;
        }
        int i = 0;
        // 发送51指令  可以省略
//        byte[] bytes = new byte[]{(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
//                (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
//                (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
//                (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x02};
//
//        i = usbDeviceConnection.controlTransfer(0xc0, 51, 0, 0, bytes, 16, 100);
//        LogUtil.e(TAG, "发送51指令 i =" + i);


        //根据AOA协议打开Accessory模式
        initStringControlTransfer(usbDeviceConnection, 0, "MediaTek"); // MANUFACTURER
        initStringControlTransfer(usbDeviceConnection, 1, "A108Plus"); // MODEL
        initStringControlTransfer(usbDeviceConnection, 2, "A108Plus"); // DESCRIPTION
        initStringControlTransfer(usbDeviceConnection, 3, "2.0"); // VERSION
        initStringControlTransfer(usbDeviceConnection, 4, "http://www.siecom.cn"); // URI
        initStringControlTransfer(usbDeviceConnection, 5, "0123456789ABCDEF"); // SERIAL
        i = usbDeviceConnection.controlTransfer(0x40, 53, 0, 0, new byte[]{}, 0, 100);
        LogUtil.e(TAG, "发送53指令 i =" + i);
        usbDeviceConnection.close();
        LogUtil.e(TAG,"AOA协议 initAccessory success");
        initDevice(usbDevice);
    }
    private void initStringControlTransfer(UsbDeviceConnection deviceConnection, int index, String string) {
        deviceConnection.controlTransfer(0x40, 52, 0, index, string.getBytes(), string.length(), 100);
        LogUtil.e(TAG,"controlTransfer----" + string);

    }

    /**
     * 初始化设备(手机) , 当手机进入Accessory模式后 , 手机的PID会变为Google定义的2个常量值其中的一个 ,
     */
    private void initDevice(final UsbDevice usbDevice) {
//        Toast.makeText(mContext,"initDevice size=" + mUsbManager.getDeviceList().size(),Toast.LENGTH_SHORT).show();
        LogUtil.e(TAG,"mUsbManager.getDeviceList().size()= " + mUsbManager.getDeviceList().size());
        if (mUsbManager.getDeviceList().size() > 0){
            mToggle = true;
        }
        if(mThreadPool == null){
            mThreadPool = Executors.newFixedThreadPool(2);
        }
        mThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                LogUtil.e(TAG,"mToggle == " + mToggle);
                while (mToggle) {
                    SystemClock.sleep(1000);

                    HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
                    LogUtil.e(TAG,"deviceList == " + deviceList.size());
                    Collection<UsbDevice> values = deviceList.values();
                    LogUtil.e(TAG,"values.size() == " + values.size() );
                    if (!values.isEmpty()) {
                        for (UsbDevice usbDevice : values) {
                            LogUtil.e(TAG,"usbDevice == " + usbDevice.getProductId() );
                            //Vid是否为0x18D1(6353) 或者0x11B8 或者 0x04e8，如果为以上Vid 中的一种，表示此设备支持accessory模式；如果不为上述Vid中的一种，则表示不支持accessory模式
                            int productId = usbDevice.getProductId();
                            LogUtil.e(TAG,"productId == " + productId);
                            //Pid是否为0x2D00 或0x2D01中的一种，如果是，则表示设备当前处于accessory模式；如果不是，则表示设备当前不处于accessory模式
                            if (productId == 0x2D00 || productId == 0x2D01) {

                                if (mUsbManager.hasPermission(usbDevice)) {
                                    LogUtil.e(TAG,"mUsbManager.hasPermission usbDevices ==  pid = " + usbDevice.getProductId());
                                    mUsbDeviceConnection = mUsbManager.openDevice(usbDevice);
                                    LogUtil.e(TAG,"mUsbDeviceConnection == " + mUsbDeviceConnection);
                                    if (mUsbDeviceConnection != null) {
                                        mUsbInterface = usbDevice.getInterface(0);
                                        int endpointCount = mUsbInterface.getEndpointCount();
                                        for (int i = 0; i < endpointCount; i++) {
                                            UsbEndpoint usbEndpoint = mUsbInterface.getEndpoint(i);
                                            if (usbEndpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
                                                if (usbEndpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
                                                    mUsbEndpointOut = usbEndpoint;
                                                } else if (usbEndpoint.getDirection() == UsbConstants.USB_DIR_IN) {
                                                    mUsbEndpointIn = usbEndpoint;
                                                }
                                            }
                                        }
                                        if (mUsbEndpointOut != null && mUsbEndpointIn != null) {
//                                            MyApplication.printLogDebug("connected success");
//                                            mHandler.sendEmptyMessage(CONNECTED_SUCCESS);
                                            LogUtil.e(TAG,"连接 success");
                                            ConstDefine.CONNECT_TYPE = ConstDefine.CONNECT_TYPE_USB; //USB连接
                                            SiecomDevice.distribution.startUSBListen(); //开始监听接收数据
                                            SiecomDevice.isConnected = true;
                                            LogUtil.e(TAG,"startConnect ----- conn == true " );
                                            loopReceiverMessage();//连接成功之后 循环接收消息
//                                            Toast.makeText(BtDeviceActivity.this,"连接 success" ,Toast.LENGTH_SHORT).show();
                                            mToggle = false;
                                            isDetached = true;

                                        }
                                    }
                                } else {
//                                    mUsbManager.requestPermission(usbDevice,
//                                            PendingIntent.getBroadcast(mContext, 0, new Intent(USB_ACTION), 0));
                                }
                            }
                        }
                    } else {
                        LogUtil.e(TAG,"Device values isEmpty");
//                        finish();
                    }
                }
            }
        });
    }

    public int sendTest(){
        if(null != mUsbDeviceConnection && null != mUsbEndpointOut){
            String messageContent = "werewrtewrerterterty";
            LogUtil.e(TAG,"mUsbDeviceConnection=" + mUsbDeviceConnection.toString() );
            LogUtil.e(TAG,"----mUsbEndpointOut=" + mUsbEndpointOut.toString());
            int i = mUsbDeviceConnection.bulkTransfer(mUsbEndpointOut, messageContent.getBytes(), messageContent.getBytes().length, 3000);

            if(i> 0){
                LogUtil.e(TAG,"发送成功 i=" + i);
            }else {
                LogUtil.e(TAG,"发送成功 失败");
            }
            return i;
        }else {
            LogUtil.e(TAG,"发送成功 失败");
            return -1;
        }

    }

    public void disConnect(){
        SiecomDevice.isConnected = false;
        if (mUsbDeviceConnection != null) {
            mUsbDeviceConnection.releaseInterface(mUsbInterface);
            mUsbDeviceConnection.close();
            mUsbDeviceConnection = null;
        }
        mUsbEndpointIn = null;
        mUsbEndpointOut = null;
        mToggle = false;
        LogUtil.e(TAG,"set Toggle false ===== conn = false");
        if(mThreadPool != null){
            mThreadPool.shutdownNow();
            mThreadPool = null;
        }
    }

    public void sendToRemote(Message.siecomproto msg) throws IOException {

        synchronized (this) {
            try {
                LogUtil.e(TAG,"toString=" + msg.toString());
                byte[] data = msg.toByteArray();
                LogUtil.e(TAG,"send data length:" + data.length);
//                LogUtil.e(TAG,"mUsbDeviceConnection=" + mUsbDeviceConnection.toString() );
//                LogUtil.e(TAG,"----mUsbEndpointOut" + mUsbEndpointOut.toString());
                //数据包最大 16K
                int i = mUsbDeviceConnection.bulkTransfer(mUsbEndpointOut,data, data.length, 3000);
                if(i> 0){
                    LogUtil.e(TAG,"发送成功 i=" + i);
                }else {

                    LogUtil.e(TAG,"发送 失败");
                }
//                msg.writeDelimitedTo(outputStream);

            } catch (Exception e) {
//                if (onReceiveListen != null)
//                    onReceiveListen.onError(e);
                e.printStackTrace();
                LogUtil.e(TAG,"发送 失败:" + e.getMessage());
                throw e;
            }
        }
    }

    byte mBytes[] = new byte[1024*16];
    ArrayList mByteArray = new ArrayList<Byte>();
    int totalLen = 0;

    /**
     * 接受消息线程 , 此线程在设备(手机)初始化完成后 , 就一直循环接受消息
     */
    private void loopReceiverMessage() {
        mThreadPool.execute(new Runnable() {
            @Override
            public void run() {
//                SystemClock.sleep(10);
                while (isReceiverMessage) {
                    /**
                     * 循环接受数据的地方 , 只接受byte数据类型的数据
                     */
                    if (mUsbDeviceConnection != null && mUsbEndpointIn != null) {

                        int i = mUsbDeviceConnection.bulkTransfer(mUsbEndpointIn, mBytes, mBytes.length, 3000);
                        if(i > 0){
                            LogUtil.e(TAG,"接收到数据长度：" + i);
                            totalLen += i;
                            byte data[] = new byte[i];
                            System.arraycopy(mBytes,0,data,0,i);
                            for(int j = 0; j< i;j++){
                                mByteArray.add(data[j]);
                            }
                            LogUtil.e(TAG,"接收到数据dataLength：" + data.length);

                            byte[] sendByte = new byte[totalLen];
                            for(int m = 0;m<sendByte.length; m++){
                                sendByte[m] = (byte)mByteArray.get(m);
                            }
                            LogUtil.e(TAG,"接收到数据mByteArray长度：" + mByteArray.size());
                            try {
                                Message.siecomproto msg = Message.siecomproto.parseFrom(sendByte);
                                LogUtil.e(TAG,"接收到数据msg：" + msg.toString());
                                LogUtil.e(TAG,"mUsbRecListen1：" + mUsbRecListen);
                                if(mUsbRecListen != null){
                                    LogUtil.e(TAG,"mUsbRecListen2：" + mUsbRecListen);
                                    mUsbRecListen.onUsbMsgReceive(msg);
                                    totalLen = 0;
                                    mByteArray.clear();
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                                LogUtil.e(TAG,"接收到消息异常：" + e.getMessage());
                            }
                            LogUtil.e(TAG,"接收到消息：" + new String(data) + "\n");
                        }

                    }
                }
            }
        });
    }

}
